/*
 * The Message class encapsulates the contents of a typical message between
 * nodes.
 * 
 * @author TCSS 558 Team 6
 * 
 * @version Spring 2013
 */

package message;

import java.io.Serializable;

/**
 * Encapsulates the contents of a message from one node to another. Contains
 * information such as the key, the Serializable value and the status of whether
 * the target key was found or not.
 * 
 * @author TCSS 558 Team 6
 * @version Spring 2013
 */
public class Message implements Serializable
{

  /** The unique message id. */
  private final String my_id;
  /**
   * The node_id of the original node that generated this message.
   */
  private final int my_origin;

  /**
   * The node id of the destination node to which this message is going.
   */
  private final int my_target;

  /**
   * The current intermediate node that on each hop.
   */
  private int my_intermediate;

  /** The mark to check if the request is finished. */
  private boolean is_Finish;

  /**
   * The key that is being searched in the system.
   */
  private final String my_key;

  /**
   * The key value containing the value getting or putting into the distributed
   * map.
   */
  private Serializable my_value;

  /**
   * The result of the request, it just gives a success or fail message.
   */
  private Serializable my_result = null;

  /**
   * The request_id is set to 0 which is a counter.
   */
  private static int request_id = 0;

  /**
   * The status of whether the target node corresponding to the key was found or
   * not.
   */
  private boolean found_target;

  /**
   *  The message type.
   */
  public final MessageType my_type;

  /**
   * @param the_origin the node it starts from
   * @param the_key key
   * @param the_value value
   * @param the_type enum
   */

  public Message(final int the_origin, final String the_key, final Serializable the_value,
                 final MessageType the_type)
  {
    this(the_origin, the_origin, the_key, the_value, the_type);
  }

  /**
   * Creates a Message object by initializing all its fields.
   * 
   * @param the_destination the node id for the destination node.
   * @param the_message parameter.
   * 
   */
  public Message(final int the_destination, final Message the_message)
  {
    this.my_target = the_destination;
    this.my_intermediate = the_message.getIntermediate();
    this.my_key = the_message.getKeyString();
    this.my_origin = the_message.getOrigin();
    this.my_type = the_message.getType();
    ++Message.request_id;
    this.my_id = "node_id_" + my_origin + "_request_" + request_id;
    this.is_Finish = the_message.isFinish();
    this.found_target = the_message.isFoundTarget();
    this.my_value = the_message.getValue();
  }

  /**
   * Constructor which takes the message type.
   * @param key_string parameter.
   * @param the_origin parameter
   * @param the_destination parameter
   * @param my_payload parameter
   * @param the_type parameter
   * 
   */
  public Message(final int the_origin, final int the_destination, final String key_string,
                 final Serializable my_payload, final MessageType the_type)
  {
    // calls the above constructor.

    my_origin = the_origin;
    my_target = the_destination;
    setIntermediate(the_origin);
    ++Message.request_id;
    this.my_id = "node_id_" + my_origin + "_request_" + request_id;
    my_key = key_string;
    my_type = the_type;
    is_Finish = false;
    found_target = false;
    my_value = my_payload;
    
  }

  /**
   * Returns the origin node id.
   * 
   * @return the origin node id.
   */
  public int getOrigin()
  {
    return my_origin;
  }
  

  /**
   * Returns the destination node id according to whether the target is found or
   * not.
   * 
   * @return if the target is found then return the origin node, otherwise
   *         return the target node.
   */

  public int getDestination()
  {
    int destination = 0;
    if (this.found_target)
    {
      destination = my_origin;
    }
    else
    {
      destination = my_target;
    }
    return destination;
  }

  /**
   * Returns the key.
   * 
   * @return the key.
   */
  public String getKeyString()
  {
    return my_key;
  }

  /**
   * Returns the value.
   * 
   * @return the value.
   */
  public Serializable getValue()
  {
    return my_value;
  }

  /**
   * Sets the value.
   * 
   * @param the_value 
   */
  public void setValue(final Serializable the_value)
  {
    this.my_value = the_value;
  }

  /**
   * Returns the status whether or not the key target was found.
   * 
   * @return whether or not the key target was found.
   */
  public boolean isFoundTarget()
  {
    return found_target;
  }

  /**
   * Sets whether or not the key target was found.
   * 
   * @param the_target whether or not the key target was found.
   */
  public void setFoundTarget(final boolean the_target)
  {
    this.found_target = the_target;
  }

  /**
   * @return the my_id
   */
  public String getMyId()
  {
    return my_id;
  }

  /**
   * @return the is_Finish
   */
  public boolean isFinish()
  {
    return is_Finish;
  }

  /**
   * @param the_Finish parameter.
   */
  public void setFinish(final boolean the_Finish)
  {
    this.is_Finish = the_Finish;
  }
  
  /**
   * @return my_type.
   */

  public MessageType getType()
  {
    return my_type;
  }

  /**
   * Return the target node id of this message.
   * 
   * @return the
   */
  public int getTarget()
  {
    return my_target;
  }

  /**
   * @return the my_intermediate
   */
  public int getIntermediate()
  {
    return my_intermediate;
  }

  /**
   * @param the_intermediate parameter.
   */
  public final void setIntermediate(final int the_intermediate)
  {
    this.my_intermediate = the_intermediate;
  }

}
